// King.cpp
//
// Created By: Jeremy Butler
// Created On: 11-Apr-2011

#include "King.h"
#include "Board.h"
#include "UnitTest.h"
#include "ChessController.h"
#include <sstream>
using namespace std;

King::King() : Piece() {
  return;
}

King::King(const Color _color) : Piece(_color, KING){
  return;
}

King::King(const King & other) : Piece(other) {
  return;
}

King * King::Clone() const{
  return new King(*this);
}

King::~King(){
  return;
}

string King::ToString() const{
  stringstream str;

  string sColor;
  if(color == WHITE)
    sColor = "White";
  else if(color == BLACK)
    sColor = "Black";
  else
    sColor = "Colorless";

  str << sColor << " King";

  return str.str();
}

set<Location> King::GetValidMoves(const Board & board, int row, int col, bool AllMoves) const{
  set<Location> validMoves;

  GetMoves1(board, row, col, validMoves);
  GetMoves2(board, row, col, validMoves);
  GetMoves3(board, row, col, validMoves);
  GetMoves4(board, row, col, validMoves);
  GetMoves5(board, row, col, validMoves);
  GetMoves6(board, row, col, validMoves);
  GetMoves7(board, row, col, validMoves);
  GetMoves8(board, row, col, validMoves);

  if(!AllMoves)
    board.RemoveCheckMoves(validMoves,row,col);

  return validMoves;
}


void King::GetMoves1(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  
  try{
    if(board(row+1,col) == NULL || board(row+1,col)->GetColor() != GetColor()){
      location.Set(col,row+1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void King::GetMoves2(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    if(board(row+1,col+1) == NULL || board(row+1,col+1)->GetColor() != GetColor()){
      location.Set(col+1,row+1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void King::GetMoves3(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    if(board(row,col+1) == NULL || board(row,col+1)->GetColor() != GetColor()){
      location.Set(col+1,row);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void King::GetMoves4(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    if(board(row-1,col+1) == NULL || board(row-1,col+1)->GetColor() != GetColor()){
      location.Set(col+1,row-1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}

void King::GetMoves5(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    if(board(row-1,col) == NULL || board(row-1,col)->GetColor() != GetColor()){
      location.Set(col,row-1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void King::GetMoves6(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    if(board(row-1,col-1) == NULL || board(row-1,col-1)->GetColor() != GetColor()){
      location.Set(col-1,row-1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void King::GetMoves7(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    if(board(row,col-1) == NULL || board(row,col-1)->GetColor() != GetColor()){
      location.Set(col-1,row);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void King::GetMoves8(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    if(board(row+1,col-1) == NULL || board(row+1,col-1)->GetColor() != GetColor()){
      location.Set(col-1,row+1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}

bool King::Test(ostream & os){
  bool success = true;

  ChessView view;
  ChessController controller(view,0);

  controller.SetView(&view);
  view.SetController(&controller);

  controller.LoadGame("games/kingTest.xml");

  set<Location> moves;

  moves = controller.model->GetValidMoves(2,4);

  TEST(moves.size() == 5);

  moves = controller.model->GetValidMoves(5,4);

  TEST(moves.size() == 8);

  return success;
}
